package p.sunmes.les.managers;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.InvalidParameterException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.badlogic.gdx.files.FileHandle;

import p.sunmes.les.data.Config;
import p.sunmes.les.util.DataDecodeInputStream;
import p.sunmes.les.util.U;

/**
 * ConfigManager.
 */
public class CM {
	private final Map<Class<? extends Config>, Map<Integer, Config>> configs = new HashMap<Class<? extends Config>, Map<Integer, Config>>();
	private final Map<String, Class<? extends Config>> readList = new HashMap<String, Class<? extends Config>>();
	public static boolean isReadEncode = false;

	public static final byte[] UTF8BOM = new byte[] { (byte) 0xEF, (byte) 0xBB,
			(byte) 0xBF };

	public void loadConfigs() {
		for (Entry<String, Class<? extends Config>> e : readList.entrySet()) {
			FileHandle fh;
			BufferedReader br = null;
			try {
				System.out.println("Load Config:" + e.getKey());
				InputStream input = null;
				if (isReadEncode) {
					fh = RM.getFile(e.getKey() + "e");
				} else {
					fh = RM.getFile(e.getKey());
				}
				input = fh.read();

				if (isReadEncode) { //加密模式,输出文件就需要去掉BOM.这里不需要判断BOM
					br = new BufferedReader(new InputStreamReader(
							new DataDecodeInputStream(input), "UTF-8"));
				} else {
					//EF BB BF  文本文件需要判断BOM
					boolean isHasBom = true;
					byte[] bomCheck = new byte[UTF8BOM.length];
					input.read(bomCheck, 0, bomCheck.length);
					for (int i = 0; i < UTF8BOM.length; i++) {
						if (bomCheck[i] != UTF8BOM[i]) {
							isHasBom = false;
							break;
						}
					}
					if (!isHasBom) {
						input.close();
						input = fh.read();
					} else {
						System.out
								.println("[" + fh.name() + "]获取到Bom头,舍弃BOM字节.");
					}

					br = new BufferedReader(
							new InputStreamReader(input, "UTF-8"));
				}
				////////

				String line = br.readLine();
				System.out.println("Fields:");
				String[] fields = line.split("\t");
				for (int i = 0; i < fields.length; i++) {
					fields[i] = fields[i].trim();
				}
				System.out.println(Arrays.toString(fields));
				if (fields.length < 2) {
					throw new IllegalArgumentException("Unknow Config!");
				}

				Map<Integer, Config> save = new HashMap<Integer, Config>();
				while ((line = br.readLine()) != null) {
					if (line.isEmpty()) {
						continue;
					}
					Map<String, String> map = readString(line, fields);
					Config config = e.getValue().newInstance();
					if (!config.readData(map)) {
						System.err.println("Config File Error! .." + line);
						U.debugErr("ReadConfig[" + e.getKey()
								+ "] Error! DataLine:" + line);
					}
					save.put(config.getId(), config);
					System.out.println("ID:" + config.getId() + " : " + map);
				}
				configs.put(e.getValue(), save);

			} catch (UnsupportedEncodingException e1) {
				e1.printStackTrace();
			} catch (InstantiationException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (IOException e1) {
				e1.printStackTrace();
			} finally {
				if (br != null) {
					try {
						br.close();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				}
			}
		}
	}

	private Map<String, String> readString(String line, String[] fields) {
		String[] values = line.split("\t");
		Map<String, String> data = new HashMap<String, String>();
		for (int i = 0; i < fields.length; i++) {
			if (values.length <= i) {
				break;
			}
			data.put(fields[i], values[i].trim());
		}
		return data;
	}

	//////////

	public void addLoadConfig(String fileName, Class<? extends Config> cls) {
		readList.put(fileName, cls);
	}

	public CM() {
	}

	@SuppressWarnings("unchecked")
	public <T> T getConfig(Class<T> cls, int id) {
		if (configs.containsKey(cls)) {
			return (T) configs.get(cls).get(id);
		} else {
			throw new InvalidParameterException(
					"没有找到配置项[" + cls.getName() + "] ID[" + id + "]");
			//return null;
		}
	}

	public Map<Integer, Config> getConfigMap(Class<? extends Config> cls) {
		return configs.get(cls);
	}

	/////////
	private static CM _instance;

	public static CM instance() {
		if (_instance == null) {
			_instance = new CM();
		}
		return _instance;
	}

	public static void dispose() {
		if (_instance != null) {
			_instance = null;
		}
	}

}
